/*
 * auth:Lyle lylechen2014@gmail.com
 * git:https://gitee.com/copperpeas/wx-bluetooth
 * 首先在微信IDE里，点击构建NPM, 比较重要
 */

const app = getApp()
var toArrayBuffer = require('to-array-buffer');
var Buffer = require('buffer/').Buffer;
import util from '../../utils/util.js';
import drawQrcode from '../../utils/weapp.qrcode.esm.js';


function inArray(arr, key, val) {
	for (let i = 0; i < arr.length; i++) {
		if (arr[i][key] === val) {
			return i;
		}
	}
	return -1;
}

// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
	var hexArr = Array.prototype.map.call(
		new Uint8Array(buffer),
		function(bit) {
			return ('00' + bit.toString(16)).slice(-2)
		}
	)
	return hexArr.join('');
}

Page({

	data: {
		devices: [],
		bindDevice: '',
		platform: 'android'
	},

	onLoad() {
		this.getSystemInfo();
	},

	//得到系统信息
	getSystemInfo() {
		let tthis = this;
		wx.getSystemInfo({
			success(res) {
				tthis.setData({
					platform: res.platform
				})
			}
		})
	},

	//重复搜索时，判断设备是否已经存在过滤掉
	findArrItem(arr, id) {
		let index = -1;
		for (let i in arr) {
			if (arr[i].deviceId == id) {
				index = i;
			}
		}
		return index;
	},

	//断开与低功耗蓝牙设备的连接
	closeBLEConnection(event) {
		let tthis = this,
			bindDevice = event.currentTarget.dataset.item;
		wx.closeBLEConnection({
			deviceId: bindDevice.deviceId
		})
		//重置属性
		tthis.setData({
			bindDevice: ''
		});
	},

	//停止蓝牙搜索
	stopBluetoothDevicesDiscovery() {
		let tthis = this;
		wx.stopBluetoothDevicesDiscovery({
			success() {
				console.log('stopBluetoothDevicesDiscovery success')
			},
			fail() {
				console.log('stopBluetoothDevicesDiscovery fail')
			}
		})
	},

	//开始搜寻附近的蓝牙设备
	startBluetoothDevicesDiscovery() {
		let tthis = this;
		//停止蓝牙搜索
		tthis.stopBluetoothDevicesDiscovery();
		//开启蓝牙搜索
		wx.startBluetoothDevicesDiscovery({
			allowDuplicatesKey: false,
			success: (res) => {
				console.log('startBluetoothDevicesDiscovery success', res)
				//搜索，监听返回结果
				tthis.onBluetoothDeviceFound()
			},
			fail: (res) => {
				console.log(res, "搜索蓝牙失败");
			}
		});
	},

	//寻找到新设备的事件的回调函数
	onBluetoothDeviceFound() {
		let tthis = this;
		wx.onBluetoothDeviceFound((res) => {
			console.log('onBluetoothDeviceFound', res);
			res.devices.forEach(device => {
				if (!device.name && !device.localName) {
					return
				}
				console.log('filter onBluetoothDeviceFound start', device, tthis.data.devices);
				const foundDevices = tthis.data.devices;
				const idx = tthis.findArrItem(foundDevices, device.deviceId);
				const data = {};
				if (idx === -1) {
					foundDevices.push(device);
				} else {
					foundDevices[idx] = device;
				}
				console.log('filter onBluetoothDeviceFound end', tthis.data.devices);
				tthis.setData({
					devices: foundDevices
				})
			})
		})
	},

	//查询蓝牙设备
	searchPrint() {
		let tthis = this;
		//避免连接过多,先断开所有连接,每次初始化才能确保稳定，想跳过的，自己在踩坑44.
		wx.closeBluetoothAdapter({
			complete: () => {
				//初始化蓝牙
				wx.openBluetoothAdapter({
					success: (res) => {
						tthis.startBluetoothDevicesDiscovery();
					},
					fail: (res) => {
						if (res.errCode === 10001) {
							console.log('蓝牙未开启');
						} else {
							console.log('蓝牙初始化失败');
						}
					}
				})
			}
		});
	},

	//绑定设备
	setBindDevice(event) {
		let tthis = this;
		//创建连接，测试设备是否可以读，可写
		tthis.createBLEConnection(event.currentTarget.dataset.item);
	},

	//低功耗蓝牙设备连接
	createBLEConnection(item, callback) {
		console.log('createBLEConnection');
		let tthis = this;
		wx.createBLEConnection({
			deviceId: item.deviceId,
			timeout: 15000,
			success: (res) => {
				console.log('蓝牙连接成功');
				tthis.setData({
					bindDevice: item
				});
				//如果蓝牙设备write没定义，说明是新设备需要执行
				if (tthis.data.platform == 'android') {
					if (item.write == undefined) {
						//检查该蓝牙设备是否有写入权限，并保存参数，以便发送数据
						tthis.getBLEDeviceServices(item.deviceId, callback);
					} else {
						callback ? callback() : ''
					}
				} else {
					tthis.getBLEDeviceServices(item.deviceId, callback);
				}

			},
			fail: (res) => {
				console.log("蓝牙连接失败:", res);
			}
		})
	},

	//获取蓝牙设备所有服务(service)
	getBLEDeviceServices(deviceId, callback) {
		let tthis = this;
		wx.getBLEDeviceServices({
			deviceId,
			success: (res) => {
				console.log('getBLEDeviceServices', res.services)
				for (let i = 0; i < res.services.length; i++) {
					if (res.services[i].isPrimary) {
						tthis.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid, callback)
						return
					}
				}
			},
			fail: (res) => {
				console.log("获取蓝牙服务失败：" + JSON.stringify(res))
			}
		})
	},

	//获取蓝牙设备某个服务中所有特征值(characteristic)
	getBLEDeviceCharacteristics(deviceId, serviceId, callback) {
		let tthis = this;
		wx.getBLEDeviceCharacteristics({
			deviceId,
			serviceId,
			success: (res) => {
				console.log('getBLEDeviceCharacteristics success', res.characteristics)
				for (let i = 0; i < res.characteristics.length; i++) {
					let item = res.characteristics[i];
					let _uuid = item.uuid;
					let bindDevice = tthis.data.bindDevice;
					// 读取低功耗蓝牙设备的特征值的二进制数据值 注意：必须设备的特征值支持 read 才可以成功调用。
					if (item.properties.read) {
						bindDevice.read = true;
					}
					//向低功耗蓝牙设备特征值中写入二进制数据。注意：必须设备的特征值支持 write 才可以成功调用。
					if (item.properties.write) {
						bindDevice.serviceId = serviceId;
						bindDevice.characteristicId = _uuid;
						bindDevice.write = true;
						callback ? callback() : ''
					}
					//启用低功耗蓝牙设备特征值变化时的 notify 功能，使用characteristicValueChange事件
					if (item.properties.notify || item.properties.indicate) {
						wx.notifyBLECharacteristicValueChange({
							deviceId,
							serviceId,
							characteristicId: _uuid,
							state: true,
						})
					}
					//设置当前选中的蓝牙设备，包括是否可读写属性采集
					tthis.setData({
						bindDevice: bindDevice
					});
					console.log(tthis.data);
				}
			},
			fail(res) {
				console.error('获取特征值失败：', res)
			}
		})
	},

	//点击打印
	clickPrint() {
		console.log('clickPrint');
		let tthis = this,
			order = '', //传递进去的打印内容
			device = tthis.data.bindDevice; //可存到后台或者本地缓存来读取传递进来
		//避免连接过多，先断开所有连接
		wx.closeBluetoothAdapter({
			success: () => {
				console.log(274, 'clickPrint');
				//初始化蓝牙
				wx.openBluetoothAdapter({
					success: (res) => {
						wx.startBluetoothDevicesDiscovery({
							allowDuplicatesKey: false,
							complete: (res) => {
								callbackOpenBluetooth();
								tthis.stopBluetoothDevicesDiscovery();
							}
						});
					},
					fail: (res) => {
						if (res.errCode === 10001) {
							console.log('蓝牙未开启!');
						} else {
							console.log('蓝牙初始化失败!');
						}
					}
				})
			}
		});

		//直接打印
		let callbackConnected = function() {
			console.log('数据生成中...');
			tthis.writeBLECharacteristicValue(device, order);
		};

		//检查设备是否连接
		let callbackOpenBluetooth = function() {
			console.log('检查设备是否连接...');
			tthis.getConnectedBluetoothDevices(device, callbackConnected);
		};
	},

	//获取已经连接的蓝牙设备,并开始打印
	getConnectedBluetoothDevices(device, callback) {
		console.log('getConnectedBluetoothDevices', device, callback);
		let tthis = this;
		wx.getConnectedBluetoothDevices({
			services: [device.serviceId],
			success(res) {
				console.log('getConnectedBluetoothDevices success', res, device);
				let devices = res.devices;
				let index = tthis.findArrItem(devices, device.deviceId);
				if (index === -1) {
					//如果该设备不是连接的，断开所有蓝牙连接
					for (let i in devices) {
						tthis.closeBLEConnection(devices[i]);
					}
					//重新连接该设备，重新点击打印，再次发送数据给打印机
					tthis.createBLEConnection(device, callback);
				} else {
					callback ? callback() : ''
				}
			}
		})
	},

	//小票打印机打印
	writeBLECharacteristicValue(device, order) {
		let tthis = this;
		let arrPrint = [];
		//初始化打印机
		arrPrint.push(util.sendDirective([0x1B, 0x40])); //16进制
		//居中对齐
		arrPrint.push(util.sendDirective([0x1B, 0x61, 0x01])); //居中
		//正文
		arrPrint.push(util.sendDirective([0x1B, 0x0E]));
		arrPrint.push(util.hexStringToBuff("\n葵花生活\n\n"));
		arrPrint.push(util.sendDirective([0x1B, 0x14]));
		arrPrint.push(util.hexStringToBuff('葵花生活测试门店1号店' + "\n"));
		arrPrint.push(util.hexStringToBuff("订单号" + 'W20154221212222' + "\n"));
		arrPrint.push(util.hexStringToBuff("--------------------------------\n"));
		arrPrint.push(util.hexStringToBuff(util.printThreeData('名称', '数量', '价格')));
		arrPrint.push(util.hexStringToBuff(util.printThreeData('衣物', 10, '3元')))
		arrPrint.push(util.hexStringToBuff("--------------------------------\n"));
		arrPrint.push(util.hexStringToBuff(util.printTwoData("总金额:", '3元')));
		arrPrint.push(util.hexStringToBuff(util.printTwoData("优惠券:", '3元')));
		arrPrint.push(util.hexStringToBuff(util.printTwoData("实付金额:", '3元')));
		arrPrint.push(util.hexStringToBuff(util.printTwoData("下单:", '2019-10-20 12:20:20')));
		arrPrint.push(util.hexStringToBuff(util.printTwoData("支付:", '已支付')));
		arrPrint.push(util.hexStringToBuff(util.printTwoData("客户:", '张三')));
		arrPrint.push(util.hexStringToBuff(util.printTwoData("电话:", '13880253762')));
		arrPrint.push(util.sendDirective([0x1B, 0x61, 0x00]));
		arrPrint.push(util.hexStringToBuff("1.请妥善保管票单，凭票取物；\n"));
		arrPrint.push(util.hexStringToBuff("2.顾客购意见及建议，请及时提出，本店积极采纳，全心全意为顾客服务\n"));
		arrPrint.push(util.hexStringToBuff("\n\n\n"));
		
		let printImgT = function() {
			tthis.printImgT(device, 'W20154221212222');
		};
		
	    //只测试文字
	    //tthis.printInfo(device, arrPrint);
		//只测试二维码
		//tthis.printImgT(device, 'W20154221212222');
		//测试文字和二维码
		tthis.printInfo(device, arrPrint, printImgT);

	},
	
	//打印二维码
	printImgT(device, text) {//小票打印
	    console.log('printImgT',Buffer);
		let tthis = this;
		const ctx = wx.createCanvasContext('canvas');
		ctx.clearRect(0, 0, 160, 160);
		drawQrcode({
			canvasId: 'canvas',
			text: String(text),
			width: 160,
			height: 160,
			callback(e) {
				setTimeout(() => {
					// 获取图片数据
					wx.canvasGetImageData({
						canvasId: 'canvas',
						x: 0,
						y: 0,
						width: 160,
						height: 160,
						success(res) {
							let arr = tthis.convert4to1(res.data);
							let data = tthis.convert8to1(arr);
							const cmds = [].concat([27, 97, 1], [29, 118, 48, 0, 20, 0, 160, 0], data, [27, 74, 3], [27, 64]);
							const buffer = toArrayBuffer(Buffer.from(cmds, 'gb2312'));
							let arrPrint = [];
							arrPrint.push(util.sendDirective([0x1B, 0x40]));
							// arrPrint.push(util.sendDirective([0x1B, 0x61, 0x01])); //居中
							for (let i = 0; i < buffer.byteLength; i = i + 20) {
								arrPrint.push(buffer.slice(i, i + 20));
							}
							arrPrint.push(util.hexStringToBuff("\n"));
							arrPrint.push(util.sendDirective([0x1B, 0x61, 0x01])); //居中
							arrPrint.push(util.hexStringToBuff("扫码识别订单号\n"));
							arrPrint.push(util.hexStringToBuff("\n"));
							arrPrint.push(util.hexStringToBuff("\n"));
							tthis.printInfo(device, arrPrint);
						}
					})
				}, 3000);
			}
		});
	},

	printInfo: function(device, arr, callback) {
		let tthis = this;
		if (arr.length > 0) {
			tthis.sendStr(device, arr[0], function(success) {
				arr.shift();
				tthis.printInfo(device, arr, callback);
			}, function(error) {
				console.log(error);
			});
		} else {
			callback ? callback() : '';
		}
	},

	//发送数据
	sendStr: function(device, bufferstr, success, fail) {
		let tthis = this;
		console.log('sendStr', device);
		wx.writeBLECharacteristicValue({
			deviceId: device.deviceId,
			serviceId: device.serviceId,
			characteristicId: device.characteristicId,
			value: bufferstr,
			success: function(res) {
				success(res);
				console.log('sendStr', bufferstr)
			},
			failed: function(res) {
				fail(res)
				console.log("数据发送失败:" + JSON.stringify(res))
			},
			// complete: function(res) {
			// 	console.log("发送完成:" + JSON.stringify(res))
			// }
		})
	},

	//4合1
	convert4to1(res) {
		let arr = [];
		for (let i = 0; i < res.length; i++) {
			if (i % 4 == 0) {
				let rule = 0.29900 * res[i] + 0.58700 * res[i + 1] + 0.11400 * res[i + 2];
				if (rule > 200) {
					res[i] = 0;
				} else {
					res[i] = 1;
				}
				arr.push(res[i]);
			}
		}
		return arr;
	},

	//8合1
	convert8to1(arr) {
		let data = [];
		for (let k = 0; k < arr.length; k += 8) {
			let temp = arr[k] * 128 + arr[k + 1] * 64 + arr[k + 2] * 32 + arr[k + 3] * 16 + arr[k + 4] * 8 + arr[k + 5] * 4 +
				arr[k + 6] * 2 + arr[k + 7] * 1
			data.push(temp);
		}
		return data;
	}




})
